//
//  PDFFactory.m
//  ActiveDeck
//
//  Created by Michael Cohen on 10/24/11.
//  Copyright (c) 2011 __MyCompanyName__. All rights reserved.
//

#import "PDFFactory.h"
#import "PageViewController.h"
#import <QuartzCore/CALayer.h>
#import "ActiveDeckViewController.h"


@implementation PDFFactory

@synthesize slides, presentationID, notebook, isCancelled, pdfPath, pdfData, documentDirectory, documentDirectories, documentDirectoryFilename, callingVC, viewsToSave, pdfBounds, username, currentPos;

int slideIndex;

/// <summary>
/// initialize and return a PDFFactory object
/// </summary>
/// <param name="presID" type="NSString*">ID of the presentation to be exported to PDF</param>
/// <param name="slidesToExport" type="NSMutableArray*">Array of AD_Slide objects</param>
/// <param name="notebookToSave" type="AD_ContainerOB*"> object with notes and photo notes</param>
/// <param name="fromVC" type="ActiveDeckViewController*"> object that is creating the PDFFactory</param>
/// <param name="uname" type="NSString*">User name of the logged in user, needed for document directory</param>
/// <param name="currentPosition" type="NSMutableArray*">Array containing current slide ID and page index</param>
/// <returns>PDFFactory</returns>
-(PDFFactory*)init:(NSString *)presID :(NSMutableArray *)slidesToExport :(AD_ContainerOB *)notebookToSave: (ActiveDeckViewController*)fromVC: (NSString*)uname: (NSMutableArray*)currentPosition{
    slideIndex = 0;
    isCancelled = NO;
    presentationID = presID;
    slides = [[NSMutableArray alloc] initWithArray:slidesToExport];
    notebook = notebookToSave;   
    callingVC = fromVC;
    username = uname;
    currentPos = [[NSMutableArray alloc] initWithArray:currentPosition];
    
    
    return self;
}

/// <summary>
/// setup the object for pdf creation
/// </summary>
-(void)initPDF{
    pdfBounds = CGRectMake(0, 0, 768, 1024);
    viewsToSave = [[NSMutableArray alloc] init];
    
    // Retrieves the document directories from the iOS device
    documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
    [documentDirectories retain];
    
    // Sets up the document file name where the pdf will be saved
    documentDirectory = [documentDirectories objectAtIndex:0];
    [documentDirectory retain];
    documentDirectoryFilename = [documentDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.pdf", presentationID]];
    [documentDirectoryFilename retain];
    
    pdfData = [[NSMutableData alloc] init];
    pdfPath = [[NSString alloc] initWithString:documentDirectoryFilename];
    UIGraphicsBeginPDFContextToData(pdfData, pdfBounds, nil);
    
    // display the progress bar
    [callingVC showPDFProgress];    
    
    [self performSelector:@selector(saveSlideToPDF:) withObject:[slides objectAtIndex:slideIndex] afterDelay:0.01];
}

/// <summary>
/// Main method to setup and save slides to pdf
/// </summary>
/// <param name="slide" type="AD_Slide">slide to be saved as PDF page</param>
/// <returns></returns>
-(void)saveSlideToPDF:(AD_Slide *)slide{
    
    // if the cancel button is tapped, clean up the PDFFactory object
    if (isCancelled) {
        [callingVC hidePDFProgress];
        [self cleanup:viewsToSave];
        [self cleanup:slides];
        
        [viewsToSave release];
        [pdfData release];
        
        UIGraphicsEndPDFContext();
        
        // jump back to the slide and page we were originally on
        [callingVC jumpSection:[[currentPos objectAtIndex:0] intValue] oldSection:0 jumpPage:[[currentPos objectAtIndex:1] intValue]];
        return;
    }
    
    // load slide into view if not the current visible slide
    if(slide.SlideID != [[currentPos objectAtIndex:0] intValue]){
        [callingVC loadViewWithSlide:slideIndex display:YES pageID:0 :YES :NO];
    }
        
    if([[callingVC slideVCSets] count] >= 1){
        // Get the SlideViewController and load all its pages
        SlideViewController *svc = [[callingVC slideVCSets] objectAtIndex:slideIndex];
        for(int i=0; i < svc.PageOBs.count; i++){
            [svc loadViewWithPage:i display:YES doTransition:NO recordToHistory:NO];
        }
        
        [self addPageViews:svc];
        
        for(id o in viewsToSave){
            [self createPDFPage:o];
        }  
        
        // After the PDF pages have been created, remove them from view        
        for (int i=0; i<svc.pageVCSets.count; i++) {
            PageViewController *pvc = (PageViewController*)[svc.pageVCSets objectAtIndex:i];
            
            if([svc SlideOB].SlideID != [[currentPos objectAtIndex:0] intValue]){
                [[pvc view] removeFromSuperview];
            } 
            else if(i != [[currentPos objectAtIndex:1] intValue]){
                [[pvc view] removeFromSuperview];                
            }
        }     
        
        [self cleanup:viewsToSave];
        
        slideIndex++;
        if (slideIndex < [slides count]) {
            // update the progress bar, then save the next slide to PDF
            [callingVC pdfBarUpdate:[NSString stringWithFormat:@"%f", (float)slideIndex/(float)[slides count]]];
            [self performSelector:@selector(saveSlideToPDF:) withObject:[slides objectAtIndex:slideIndex] afterDelay:0.01]; 
        } else {
            // we're done saving slides
            UIGraphicsEndPDFContext();
            // instructs the mutable data object to write its context to a file on disk
            [pdfData writeToFile:documentDirectoryFilename atomically:YES];
            pdfPath = [[NSString alloc] initWithFormat:@"%@",documentDirectoryFilename];
            
            int section = [[currentPos objectAtIndex:0] intValue];
            int page = [[currentPos objectAtIndex:1] intValue];
            // return to the slide and page the user was viewing
            [callingVC jumpSection:section oldSection:0 jumpPage:page];
            
            [self promptToOpenPDF];
            
            // hide the progress bar
            [callingVC hidePDFProgress];
        }  
        
    }

}

/// <summary>
/// quick method for cleaning up an array
/// </summary>
/// <param name="array" type="NSMutableArray*">array to be emptied</param>
/// <returns></returns>
-(void)cleanup:(NSMutableArray*)array{
    for(int j=0; j < array.count; j++){
        [array replaceObjectAtIndex:j withObject:[NSNull null]];           
    }
    
    [array removeAllObjects];
}


/// <summary>
/// renders to pdf context
/// </summary>
/// <param name="objectForPDF" type="id">object to be rendered to PDF context.  Currently only PageViewController, AD_Note and AD_PhotoNote are accepted</param>
/// <returns></returns>
-(void)createPDFPage:(id)objectForPDF{
    UIGraphicsBeginPDFPage();
    
    if ([objectForPDF isKindOfClass:[PageViewController class]]) {
        PageViewController *pvc = (PageViewController*)objectForPDF;
        
        // hide the presentation container, render the view to the pdf context
        [[pvc Bar_Container] setHidden:YES];
        [[pvc Bar_UpperContainer] setHidden:YES];
        
        [pvc.view.layer renderInContext:UIGraphicsGetCurrentContext()];
        
        [[pvc Bar_Container] setHidden:NO];
        [[pvc Bar_UpperContainer] setHidden:NO];
        
    } else if([objectForPDF isKindOfClass:[AD_Note class]]){
        
        // render text to the pdf
        CGRect textRect = CGRectMake(10, 10, pdfBounds.size.width, pdfBounds.size.height);
        AD_Note *note = (AD_Note*)objectForPDF;
        [note.Txt_Note drawInRect:textRect withFont:[UIFont systemFontOfSize:16.0f]];
        
    }else if([objectForPDF isKindOfClass:[AD_PhotoNote class]]){
        
        // get the saved image, render it to pdf
        AD_PhotoNote *photoNote = (AD_PhotoNote*)objectForPDF;
        NSString *imagePath = [NSString stringWithFormat:@"%@/%@/Container/%@/%@", documentDirectory, presentationID, username ,photoNote.Path_Image];
        UIImage *theImage = [[UIImage alloc] initWithContentsOfFile:imagePath];
        NSLog(@"The Image width: %f, height: %f", theImage.size.width, theImage.size.height);
        CGRect imageRect = CGRectMake(pdfBounds.size.width/4, pdfBounds.origin.y, pdfBounds.size.width*0.5f, pdfBounds.size.height*0.5f);
        [theImage drawInRect:imageRect];
        
        // render associated text to pdf
        CGRect photoTextRect = CGRectMake(10, (pdfBounds.size.height / 2) + 10, pdfBounds.size.width, (pdfBounds.size.height / 2) - 10);
        [photoNote.Txt_Note drawInRect:photoTextRect withFont:[UIFont systemFontOfSize:16.0f]];
    }
}

/// <summary>
/// adds all Pages in a slide to a class array
/// </summary>
/// <param name="svc" type="SlideViewController">The slide to be parsed</param>
/// <returns></returns>
- (void)addPageViews:(SlideViewController *)svc {
    if(svc.pageVCSets.count >= 1){    
        for(PageViewController *pvc in svc.pageVCSets){
            [viewsToSave addObject:pvc];
        }
        
        int noteIndex = [notebook.Array_Note indexOfObjectPassingTest:^BOOL(AD_Note *note, NSUInteger idx, BOOL *stop) {
            return note.SlideIndex == svc.SlideIndex;
        }];
        
        if(noteIndex <= slides.count-1){
            AD_Note *thisNote = [notebook.Array_Note objectAtIndex:noteIndex];                        
            
            [viewsToSave addObject:thisNote];
        }
        
        int photoIndex = [notebook.Array_Photo indexOfObjectPassingTest:^BOOL(AD_PhotoNote *photo, NSUInteger idx, BOOL *stop) {
            return photo.SlideIndex == svc.SlideIndex;
        }];
        
        if (photoIndex <= slides.count-1) {
            AD_PhotoNote *thisPhotoNote = [notebook.Array_Photo objectAtIndex:photoIndex];
            
            
            [viewsToSave addObject:thisPhotoNote];
        }
    }
}

/// <summary>
/// sets up and displays the popup for exporting the PDF to other apps
/// </summary>
/// <returns></returns>
-(void)promptToOpenPDF{
    NSLog(@"documentDirectoryFileName: %@",pdfPath);
    
    NSURL *url = [NSURL fileURLWithPath:pdfPath];
    
    docController = [UIDocumentInteractionController interactionControllerWithURL:url];
    docController.delegate = self;
    
    [docController retain];
    
    
    [docController presentOpenInMenuFromRect:CGRectMake(675, 30, 0, 0) inView:callingVC.view animated:YES];
    
}


- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller
{
	return callingVC;
}

- (UIView *)documentInteractionControllerViewForPreview:(UIDocumentInteractionController *)controller
{
	return callingVC.view;
}

- (CGRect)documentInteractionControllerRectForPreview:(UIDocumentInteractionController *)controller
{
	return callingVC.view.frame;
}

- (void)documentInteractionControllerDidDismissOptionsMenu:(UIDocumentInteractionController *)controller{
	//[controller release];
}

-(void)dealloc{
    [slides release];
    [notebook release];
    [super dealloc];
}

@end
